/*
 *Copyright (c) [2019-2020]  C2comm, Inc.  All rights reserved.
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; If not, see <https://www.gnu.org/licenses/>
 */

/*
 *Vendor: C2comm
 *Version: 1.0
 *Filename: CliqueDetect.v
 *Target Device: Altera
 *Author : 刘晓骏
*/

module CliqueDetect(
    input  wire         SYS2CORE_clk,
    input  wire         SYS2CORE_rst_n,
    
    input  wire [336:0] CONF2CORE_cm_static_conf,
    
    input  wire [ 19:0] G_local_clk,
    input  wire [  5:0] G_Integration_Cycle,
    
    input  wire         SCP2CD_sync_des_valid,
    input  wire [ 17:0] SCP2CD_sync_des,
    
    output wire [  5:0] CD2SCT_clique_in,

    input  wire         state_clr_trigger,//状态机中的清零条件
    //针对local_clk/local_integrate_cycle/local_sync/async_membership
    
    output wire [298:0] CORE2MON_cm_state
);
/*//////////////////////////////////////////////////////////
                    中间变量声明区域
*///////////////////////////////////////////////////////////
//本模块中所有中间变量(wire/reg/parameter)在此集中声明 
reg  [ 7:0] curr_localSyncMembership;
reg  [ 3:0] curr_localSyncMembersum;

reg  [ 7:0] curr_localAsyncMembership[1:0];
       
reg  [ 7:0] next_localSyncMembership;
reg  [ 3:0] next_localSyncMembersum;

reg  [ 7:0] next_localAsyncMembership[1:0];


wire [ 4:0] next_localAsyncMembersum[1:0];

reg         sync_eval_trigger;
reg  [ 1:0] async_eval_trigger;



reg  [19:0] async_mon_endpit;

localparam CM_INTEGRATE  = 6'b000001,
           CM_UNSYNC     = 6'b000010,
           CM_CA_ENABLED = 6'b000100,
           CM_WAIT_4_IN  = 6'b001000,
           CM_SYNC       = 6'b010000,
           CM_STABLE     = 6'b100000;

//***************************************************
//              状态统计信号
//***************************************************          
assign CORE2MON_cm_state = {67'b0,
                            next_localSyncMembership,
                            next_localAsyncMembership[0],
                            next_localAsyncMembership[1],
                            208'b0};
//***************************************************
//           更新LocalSyncMembership
//***************************************************

always @(posedge SYS2CORE_clk) sync_eval_trigger <= (G_local_clk == CONF2CORE_cm_static_conf[59:40]);




always @* begin
    if((sync_eval_trigger == 1'b1) || (state_clr_trigger == 1'b1))begin
        next_localSyncMembership = 8'b0;
        next_localSyncMembersum  = 4'b0;
    end
    else if((SCP2CD_sync_des_valid == 1'b1) && 
           ((SCP2CD_sync_des[14:12] > 3'b0) || (SCP2CD_sync_des[17] == 1'b1))
           ) begin
        next_localSyncMembership = SCP2CD_sync_des[ 7:0];
        next_localSyncMembersum  = SCP2CD_sync_des[11:8];
        end
    else begin//保持原值
        next_localSyncMembership = curr_localSyncMembership;
        next_localSyncMembersum  = curr_localSyncMembersum;
    end
end

always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(SYS2CORE_rst_n == 1'b0) begin
        curr_localSyncMembership <= 8'b0;
        curr_localSyncMembersum  <= 4'b0;
    end
    else begin
        curr_localSyncMembership <= next_localSyncMembership;
        curr_localSyncMembersum  <= next_localSyncMembersum;
    end
end

//***************************************************
//           更新LocalAsyncMembership
//***************************************************

always @(posedge SYS2CORE_clk) async_mon_endpit <= CONF2CORE_cm_static_conf[79:60] + CONF2CORE_cm_static_conf[274:256];


always @(posedge SYS2CORE_clk) begin
    async_eval_trigger[0] <= (G_local_clk == CONF2CORE_cm_static_conf[39:20]) & (G_Integration_Cycle[0] == 1'b0);
    async_eval_trigger[1] <= (G_local_clk == CONF2CORE_cm_static_conf[39:20]) & (G_Integration_Cycle[0] == 1'b1);
end


always @* begin
    if((async_eval_trigger[0] == 1'b1) || 
       (state_clr_trigger == 1'b1)  || 
       ((SCP2CD_sync_des_valid == 1'b1) && (SCP2CD_sync_des[14:12] > 3'b0))
      )begin
        next_localAsyncMembership[0] = 8'b0;
    end
    else if((SCP2CD_sync_des_valid == 1'b1) && 
            (SCP2CD_sync_des[17] == 1'b0) && 
            (G_local_clk<=async_mon_endpit)
           )begin
        next_localAsyncMembership[0] = curr_localAsyncMembership[0] | SCP2CD_sync_des[7:0];
    end
    else begin
        next_localAsyncMembership[0] = curr_localAsyncMembership[0];
    end
end


always @* begin
    if((async_eval_trigger[1] == 1'b1) || 
       (state_clr_trigger == 1'b1)  || 
       ((SCP2CD_sync_des_valid == 1'b1) && (SCP2CD_sync_des[14:12] > 3'b0))
      )begin
        next_localAsyncMembership[1] = 8'b0;
    end
    else if((SCP2CD_sync_des_valid == 1'b1) && 
            (SCP2CD_sync_des[17] == 1'b0) && 
            (G_local_clk>=CONF2CORE_cm_static_conf[79:60])
           )begin
        next_localAsyncMembership[1] = curr_localAsyncMembership[1] | SCP2CD_sync_des[7:0];
    end
    else begin//保持原值
        next_localAsyncMembership[1] = curr_localAsyncMembership[1];
    end
end

always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(SYS2CORE_rst_n == 1'b0) begin
        curr_localAsyncMembership[0] <= 8'b0;
        curr_localAsyncMembership[1] <= 8'b0;
    end
    else begin
        curr_localAsyncMembership[0] <= next_localAsyncMembership[0];
        curr_localAsyncMembership[1] <= next_localAsyncMembership[1];
    end
end

//***************************************************
//           Clique_Detect条件判断
//***************************************************
                         
assign next_localAsyncMembersum[0] = next_localAsyncMembership[0][0] + 
                                     next_localAsyncMembership[0][1] + 
                                     next_localAsyncMembership[0][2] + 
                                     next_localAsyncMembership[0][3] + 
                                     next_localAsyncMembership[0][4] + 
                                     next_localAsyncMembership[0][5] + 
                                     next_localAsyncMembership[0][6] + 
                                     next_localAsyncMembership[0][7];
                                     
assign next_localAsyncMembersum[1] = next_localAsyncMembership[1][0] + 
                                     next_localAsyncMembership[1][1] + 
                                     next_localAsyncMembership[1][2] + 
                                     next_localAsyncMembership[1][3] + 
                                     next_localAsyncMembership[1][4] + 
                                     next_localAsyncMembership[1][5] + 
                                     next_localAsyncMembership[1][6] + 
                                     next_localAsyncMembership[1][7];
                                  
assign CD2SCT_clique_in[0] = (next_localSyncMembersum  <  CONF2CORE_cm_static_conf[91:88]);

assign CD2SCT_clique_in[1] = (next_localSyncMembersum  >= CONF2CORE_cm_static_conf[91:88]);

assign CD2SCT_clique_in[2] = (next_localSyncMembersum  <  CONF2CORE_cm_static_conf[83:80]);

assign CD2SCT_clique_in[3] = (next_localSyncMembersum  >= CONF2CORE_cm_static_conf[83:80]);

//任意一个满足即触发
assign CD2SCT_clique_in[4] = (next_localAsyncMembersum[0] >= CONF2CORE_cm_static_conf[95:92]) | 
                             (next_localAsyncMembersum[1] >= CONF2CORE_cm_static_conf[95:92]);
                             
assign CD2SCT_clique_in[5] = (next_localAsyncMembersum[0] >= CONF2CORE_cm_static_conf[87:84]) | 
                             (next_localAsyncMembersum[1] >= CONF2CORE_cm_static_conf[87:84]);
                                                
/*//////////////////////////////////////////////////////////
                   IP调用区域
*///////////////////////////////////////////////////////////
//本模块调用的所有IP在该区域实例化
//例如fifo/ram/grant之类的IP.... 
endmodule
/*
CliqueDetect CliqueDetect_inst(
    .SYS2CORE_clk(),
    .SYS2CORE_rst_n(),

    .CONF2CORE_cm_static_conf(),

    .G_local_clk(),
    .G_Integration_Cycle(),

    .SCP2CD_sync_des_valid(),
    .SCP2CD_sync_des(),

    .CD2SCT_clique_in(),

    .state_clr_trigger(),//状态机中的清零条件
    //针对local_clk/local_integrate_cycle/local_sync/async_membership
    
    .CORE2MON_cm_state()
);
*/